﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace SimpleGame.Font
{
    public sealed class FontManager
    {
        // There can only be one highla... FontManager
        static readonly FontManager instance = new FontManager();

        #region Fields

        // The ScreenManager's SpriteBatch reference for easy drawing
        private SpriteBatch spriteBatchRef;

        // Holds all the SimpleFonts in the game and their respective name
        private Dictionary<string, SimpleFont> fonts = new Dictionary<string, SimpleFont>();

        #endregion

        #region Properties

        public static FontManager Instance
        {
            get { return instance; }
        }

        public SpriteBatch SpriteBatchRef
        {
            set { spriteBatchRef = value; }
        }

        #endregion

        #region Constructors

        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static FontManager() {}

        #endregion

        #region Collection Methods

        /// <summary>
        /// Adds a SimpleFont to the FontManager for easy access.
        /// </summary>
        /// <param name="font">The SimpleFont to be added</param>
        public void AddFont(SimpleFont font)
        {
            if (!fonts.ContainsKey(font.Name))
            {
                fonts.Add(font.Name, font);
            }
        }

        /// <summary>
        /// Removes a SimpleFont from the FontManager.
        /// </summary>
        /// <param name="font">The SimpleFont to be removed</param>
        public void RemoveFont(SimpleFont font)
        {
            fonts.Remove(font.Name);
        }

        /// <summary>
        /// Removes a SimpleFont from the FontManager.
        /// </summary>
        /// <param name="name">The name of the SimpleFont to be removed</param>
        public void RemoveFont(string name)
        {
            fonts.Remove(name);
        }
        
        /// <summary>
        /// Returns a SimpleFont from the FontManager by name or the default font if there is no
        /// SimpleFont with that specific name in the FontManager.
        /// </summary>
        /// <param name="name">The name of the SimpleFont</param>
        /// <returns>The SimpleFont with the given name</returns>
        public SimpleFont GetFont(string name)
        {
            if (fonts.ContainsKey(name))
            {
                return fonts[name];
            }
#if DEBUG
            Debug.WriteLine("!!! Font not found! Returning default font.");
#endif
            return GetFont("default");
        }

        #endregion

        #region Basic DrawString Methods

        /// <summary>
        /// Draws a string using the defined SimpleFont. If the font has not yet been added to the SimpleFont dictionary
        /// it will do so automatically.
        /// </summary>
        /// <param name="font">The SimpleFont to be used</param>
        /// <param name="text">The text to be drawn</param>
        /// <param name="position">The position of the text</param>
        /// <param name="color">The color of the text</param>
        /// <param name="scale">The scale of the text</param>
        /// <param name="rotation">The rotation of the text</param>
        /// <param name="rotationOrigin">The origin of the rotation</param>
        public void DrawString(
            SimpleFont font,
            string text,
            Vector2 position,
            Color color,
            float scale,
            float rotation,
            Vector2 rotationOrigin)
        {
            // check if font is null
            if (font == null)
            {
#if DEBUG
                Debug.WriteLine("!!! Font instance is null! using default font.");
#endif
                // if font is null use default font instead
                font = GetFont("default");
            }
            else
            {
                // make sure the SimpleFont used is added to the Collection if not yet in it
                AddFont(font);
            }

            // actual drawing
            spriteBatchRef.DrawString(
                font.SpriteFont,
                text,
                position,
                color,
                rotation,
                rotationOrigin,
                scale,
                SpriteEffects.None,
                0);
        }

        /// <summary>
        /// Draws a string using the defined SimpleFont by font name. If the font has not yet been added to the SimpleFont dictionary
        /// it will do so automatically.
        /// </summary>
        /// <param name="fontName">The name SimpleFont to be used</param>
        /// <param name="text">The text to be drawn</param>
        /// <param name="position">The position of the text</param>
        /// <param name="color">The color of the text</param>
        /// <param name="scale">The scale of the text</param>
        /// <param name="rotation">The rotation of the text</param>
        /// <param name="rotationOrigin">The origin of the rotation</param>
        public void DrawString(
            string fontName,
            string text,
            Vector2 position,
            Color color,
            float scale,
            float rotation,
            Vector2 rotationOrigin)
        {
            DrawString(
                GetFont(fontName),
                text,
                position,
                color,
                scale,
                rotation,
                rotationOrigin);
        }

        /// <summary>
        /// Draws a string using the default font
        /// </summary>
        /// <param name="text">The text to draw</param>
        /// <param name="position">The position where to draw</param>
        /// <param name="color">The color of the text</param>
        public void DrawString(SpriteBatch spriteBatch, string text, Vector2 position, Color color)
        {
            DrawString(
                "default",
                text,
                position,
                color,
                1.0f,
                0.0f,
                Vector2.Zero);
        }

        #endregion

        #region Shadow DrawString Methods

        /// <summary>
        /// Draws a text with shadow.
        /// </summary>
        /// <param name="font">The SimpleFont to be used</param>
        /// <param name="text">The text to be drawn</param>
        /// <param name="position">The position of the text</param>
        /// <param name="color">The color of the text</param>
        /// <param name="scale">The scale of the text</param>
        /// <param name="rotation">The rotation of the text</param>
        /// <param name="rotationOrigin">The origin of the rotation</param>
        /// <param name="shadowColor">The color of the shadow</param>
        /// <param name="shadowOffset">The X and Y offset of the shadow</param>
        /// <param name="shadowScale">the scale of the shadow</param>
        public void DrawStringShadowed(
            SimpleFont font,
            string text,
            Vector2 position,
            Color color,
            float scale,
            float rotation,
            Vector2 rotationOrigin,
            Color shadowColor,
            Vector2 shadowOffset,
            float shadowScale)
        {
            // draw shadow
            DrawString(
                font,
                text,
                position + shadowOffset,
                shadowColor,
                shadowScale,
                rotation,
                rotationOrigin);
            // draw string
            DrawString(
                font,
                text,
                position,
                color,
                scale,
                rotation,
                rotationOrigin);
        }

        /// <summary>
        /// Draws a text with shadow. 
        /// </summary>
        /// <param name="fontName">The name of the SimpleFont to be used</param>
        /// <param name="text">The text to be drawn</param>
        /// <param name="position">The position of the text</param>
        /// <param name="color">The color of the text</param>
        /// <param name="scale">The scale of the text</param>
        /// <param name="rotation">The rotation of the text</param>
        /// <param name="rotationOrigin">The origin of the rotation</param>
        /// <param name="shadowColor">The color of the shadow</param>
        /// <param name="shadowOffset">The X and Y offset of the shadow</param>
        /// <param name="shadowScale">the scale of the shadow</param>
        public void DrawStringShadowed(
            string fontName,
            string text,
            Vector2 position,
            Color color,
            float scale,
            float rotation,
            Vector2 rotationOrigin,
            Color shadowColor,
            Vector2 shadowOffset,
            float shadowScale)
        {
            // draw shadow
            DrawString(
                GetFont(fontName),
                text,
                position + shadowOffset,
                shadowColor,
                shadowScale,
                rotation,
                rotationOrigin);
            // draw string
            DrawString(
                GetFont(fontName),
                text,
                position,
                color,
                scale,
                rotation,
                rotationOrigin);
        }

        #endregion
    }
}
